#pragma once

#include "crypto.h"

namespace EurekaCryptoServiceProvider
{
#define KEY_RAND_LOWER	8
#define KEY_RAND_UPPER	16

	// generate a 7~15 bit key
	int GenerateKey(OUT LPBYTE buffer)
	{
		int len = rand() % (KEY_RAND_UPPER - KEY_RAND_LOWER) + KEY_RAND_LOWER;

		for(int i=0; i<len; i++)
		{
			buffer[i] = rand() % 0xFF;
		}

		return len;
	}

	int EncryptString(IN OUT LPBYTE buffer, int nLen, int key)
	{
		for(int i=0; i<nLen; i++)
		{
			BYTE x = buffer[i];
			buffer[i] = (x << key) | (x >> (8 - key));
		}
		return nLen;
	}

	int DecryptString(IN OUT LPBYTE buffer, int nLen, int key)
	{
		for(int i=0; i<nLen; i++)
		{
			BYTE x = buffer[i];
			buffer[i] = (x >> key) | (x << (8 - key));
		}
		return nLen;
	}

	int ShellCryptPackage(IN OUT LPBYTE buffer, int nLen)
	{
		for(int i=0; i<nLen; i++)
		{
			if(buffer[i] % 2)
				buffer[i] += 1;
			else
				buffer[i] -= 1;
		}

		return nLen;
	}

	inline char Asic2Hex(const char x)
	{
		if(x>='A' && x<='F')
			return x - 'A' + 10;
		else
			return x - '0';
	}

	inline char Hex2Asic(const char x)
	{
		if(x>=0xA && x<=0xF)
			return x + 'A' - 10;
		else
			return x + '0';
	}

	/// <summary>
	/// IN      07 55 24 00 01
	/// OUT     "0755240001"
	/// </summary>
	int Byte2String(IN LPCBYTE buffer, int nLen, OUT LPSTR szText)
	{
		char* p = szText;
		for(int i=0; i<nLen; i++)
		{
			*p++ = Hex2Asic(buffer[i] / 0x10);
			*p++ = Hex2Asic(buffer[i] % 0x10);
		}
		*p = '\0';
		return nLen * 2;
	}

	/// <summary>
	/// IN      "0755240001"
	/// OUT     07 55 24 00 01
	/// </summary>
	int String2Byte(IN LPCSTR szText, OUT LPBYTE buffer)
	{
		int len = 0;
		char* p = (char*)szText;
		while(*p)
		{
			buffer[len++] = Asic2Hex(*p) * 0x10 + Asic2Hex(*(p+1));
			p += 2;
		}

		return len;
	}

}